/*---------------------------------------------------------------------------*
 *  SRecTestAudio.c  *
 *                                                                           *
 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
 *                                                                           *
 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
 *  you may not use this file except in compliance with the License.         *
 *                                                                           *
 *  You may obtain a copy of the License at                                  *
 *      http://www.apache.org/licenses/LICENSE-2.0                           *
 *                                                                           *
 *  Unless required by applicable law or agreed to in writing, software      *
 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 
 *  See the License for the specific language governing permissions and      *
 *  limitations under the License.                                           *
 *                                                                           *
 *---------------------------------------------------------------------------*/


#ifdef _WIN32
  #include <windows.h>
  #include <mmsystem.h>
  #include "signal.h"
  #include "direct.h"
#endif

#include "passert.h"
#include "ESR_CommandLine.h"
#include "ESR_Session.h"
#include "LCHAR.h"
#include "PFile.h"
#include "PFileSystem.h"
#include "PANSIFileSystem.h"
//#include "PMemoryFileSystem.h"
#include "plog.h"
#include "pmemory.h"
#include "ptypes.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#if defined(APP_ENABLE_TIMER)
#include "ptimer.h"
#endif
#include "SR_Grammar.h"
#include "SR_Recognizer.h"
#include "SR_RecognizerResult.h"
#include "SR_Session.h"
#include "SR_Vocabulary.h"
#include "SR_AcousticState.h"
#include "SR_Nametag.h"
#include "PStackSize.h"

#ifdef ACCURACY_TESTING
#include "SR_GrammarImpl.h"
#include "SR_SemanticProcessorImpl.h"
#endif

#include "audioin.h"
#include "srec_test_config.h"

//Define this in makefile
//#define _DEBUGHEAP


#if defined(_DEBUGHEAP) && defined(_DEBUG) && defined(WIN32)
#include <crtdbg.h>
#endif


#define SREC_TEST_DEFAULT_AUDIO_FREQUENCY       11025
#define LOG_BUFFER_SIZE                         512
#define MAX_AUDIO_BUFFER_SIZE                   2048
#define DEFAULT_AUDIO_BUFFER_SIZE               256
#define MAX_LINE_LENGTH                         255
#define TRANSCRIPTION_SIZE                      512
#define MAX_SCORE_LENGTH                        5
#define MAX_NUM_REC_CONTEXTS                    4


#ifdef PFILE_VIRTUAL_SUPPORT
  extern const FileRecord pFileRecTable[];
  extern const unsigned char pFileStart0[];
#endif /* #ifdef PFILE_VIRTUAL_SUPPORT */

typedef enum
    {
    SENTENCE_BEGIN,
    SENTENCE_BEGIN_BRACKET_BEGIN,
    SENTENCE_BEGIN_BRACKET_END,
    SENTENCE_MIDDLE,
    SENTENCE_MIDDLE_BRACKET_BEGIN,
    SENTENCE_MIDDLE_BRACKET_END,
    SENTENCE_MIDDLE_WITH_SPACE
    } SENTENCE_CLEANING_STATES;



typedef enum
    {
    ForcedRecModeNotSet = -1,
    ForcedRecModeOff=0,
    ForcedRecModeOneTime,
    ForcedRecModeOn
    } ForcedRecMode;


typedef enum
    {
    ERROR_LEVEL_CRITICAL = 0,
    ERROR_LEVEL_HIGH,
    ERROR_LEVEL_MODERATE,
    ERROR_LEVEL_LOW
    } SREC_TEST_ERROR_LEVELS;


typedef struct
    {
    LCHAR       grammar_path [P_PATH_MAX];      /* File path of the grammar. */
    LCHAR       grammarID [P_PATH_MAX];         /* ID of the grammar. */
    LCHAR       ruleName  [P_PATH_MAX];         /* rule name of the grammar. */
    SR_Grammar* grammar;                        /* grammar. */
    ESR_BOOL        is_ve_grammar;                  /* Is voice-enrollment grammar or not */
    } APPL_GRAMMAR_DATA;


typedef struct ApplicationData_t
    {
    int                         argc;           /* The number of command-line arguments. */
    LCHAR                       **argv;         /* The command-line argument values. */
    PFile                       *outputLog;     /* Output log. */
    ESR_Locale                  locale;         /* Current application locale. */
    SR_Recognizer               *recognizer;    /* The current recognizer. */
    SR_RecognizerResult         *result;        /* The last recognition result. */
    SR_Vocabulary               *vocabulary;    /* The current vocabulary. */
    SR_Nametag                  *nametag;       /* The nametag generated by the last recognition. */
    SR_Nametags                 *nametags;      /* The active nametag collection. */
    APPL_GRAMMAR_DATA           grammars [MAX_NUM_REC_CONTEXTS];        /* Grammar data */
    int                         grammarCount;   /* The number of grammars. */
    int                         active_grammar_num;     /* The index number of the active grammar. */
    const asr_int16_t                 *raw_waveform;  /*Points to raw waveform returned from voice enrollment */
    size_t                      raw_waveform_size;  /* Size of above wave_form */
    asr_int16_t                 audio_buffer [MAX_AUDIO_BUFFER_SIZE];
    size_t                      audio_buffer_requested_size;
    size_t                      num_samples_read;
    LCHAR                       raw_waveform_filename [P_PATH_MAX];     /* Name of file of saved waveform data. */
    PFile                       *raw_waveform_file;     /* Pointer to file of saved waveform data. */
    LCHAR                       transcription [MAX_LINE_LENGTH];
    ForcedRecMode               forced_rec_mode;
    } ApplicationData;



static int      srec_test_get_run_params ( unsigned int *num_shutdown_loops, unsigned int *num_continuous_run_loops );
static int      srec_test_init_application_data ( ApplicationData *applicationData, int arg_count, LCHAR *arg_vals [] );
static int      srec_test_init_file_system ( int arg_count, LCHAR *arg_vals [] );
static int      srec_test_init_logging_system ( int arg_count, LCHAR *arg_vals [], PLogger *logger );
static int      srec_test_init_memory_system ( unsigned int srec_test_heap_size );
static int      srec_test_init_system ( unsigned int srec_test_heap_size, PLogger* logger, int arg_count,
                                        LCHAR *arg_vals [], AUDIOIN_H *audio_input_handle );
static int      srec_test_run_test_execute ( ApplicationData *applicationData, AUDIOIN_H audio_input_handle );
static int      srec_test_run_test_init ( ApplicationData *applicationData );
static int      srec_test_run_test ( ApplicationData *applicationData, AUDIOIN_H audio_input_handle );
static int      srec_test_shutdown_file_system ( void );
static int      srec_test_shutdown_logging_system ( PLogger *logger );
static int      srec_test_shutdown_memory_system ( void );
static int      srec_test_recognize_live ( SR_Grammar *active_grammar, ApplicationData *data, AUDIOIN_H audio_input_handle,
                                           FILE *results_file, size_t *recognition_count );
static void     srec_test_log_recognition_failure ( ApplicationData *data );



static ESR_BOOL interrupted = ESR_FALSE;

/* static ESR_BOOL no_enroll = ESR_FALSE;      //BJP */

int signal_handler_SIGINT(int v)
{
  interrupted = ESR_TRUE;
  return 0;
}



ESR_ReturnCode myDSMCallback(LCHAR* functionName, LCHAR** argv, size_t argc, void* value, LCHAR* result, size_t* resultSize)
{
  LCHAR* meaning;

  PLOG_DBG_TRACE((L("myDSMCallback(%s) invoked\n"), functionName));
  if ((LSTRCMP(functionName, "myDSMCallback")!=0) || (argc > 1))
  {
    /* Unsupported semantic function */
    return ESR_INVALID_STATE;
  }
        if (argc > 0)
                meaning = argv[0];
        else
                meaning = L("");
  lstrtrim(meaning);
  LSTRLWR(meaning);

  if (LISDIGIT(*meaning))
        {
                /* Penalize meaning starting with "<digit>" */
    if (*resultSize < LSTRLEN(L("1000"))+1)
    {
      *resultSize = LSTRLEN(L("1000"))+1;
      return ESR_BUFFER_OVERFLOW;
    }
    LSTRCPY(result, "1000");
    *resultSize = LSTRLEN(L("1000"))+1;
    return ESR_SUCCESS;
        }
  if (*resultSize < LSTRLEN(L("0"))+1)
  {
    *resultSize = LSTRLEN(L("0"))+1;
    return ESR_BUFFER_OVERFLOW;
  }
  LSTRCPY(result, "0");
  *resultSize = LSTRLEN(L("0"))+1;
  return ESR_SUCCESS;
}



void srec_test_log_error ( unsigned int error_id, SREC_TEST_ERROR_LEVELS error_level, LCHAR *error_text )
    {

    switch ( error_level )
        {
        case ERROR_LEVEL_CRITICAL:
            LPRINTF ( "Critical Level Error %s\n", error_text );
            break;

        case ERROR_LEVEL_HIGH:
            LPRINTF ( "High Level Error %s\n", error_text );
            break;

        case ERROR_LEVEL_MODERATE:
            LPRINTF ( "Moderate Level Error %s\n", error_text );
            break;

        case ERROR_LEVEL_LOW:
            LPRINTF ( "Low Level Error %s\n", error_text );
            break;

        default:
            LPRINTF ( "Unknown Level Error %d  :  %s\n", error_level, error_text );
            break;
        }
    }



void srec_test_delete_grammar ( ApplicationData *data, int grammar_num )
    {
    LCHAR log_buffer[LOG_BUFFER_SIZE];

    if ( grammar_num < data->grammarCount )
        {
        if ( ( data->grammarCount - grammar_num ) > 1 )
            {
            memmove ( &data->grammars [grammar_num], &data->grammars [data->grammarCount - 1],
                      ( data->grammarCount - grammar_num - 1 ) * sizeof ( APPL_GRAMMAR_DATA ) );
            if ( grammar_num > data->active_grammar_num )
                data->active_grammar_num--;
            }
        data->grammarCount--;
        }
    else
        {
        LSPRINTF ( log_buffer, L("Internal Error Grammar TableCorrupt : Grammar %d Does Not Exist"), grammar_num );
        srec_test_log_error ( 0, ERROR_LEVEL_CRITICAL, log_buffer );
        }
    }



static void srec_test_get_active_grammar ( ApplicationData *data, SR_Grammar **active_grammar )
    {

    if ( data->active_grammar_num >= 0 )
        *active_grammar = data->grammars [data->active_grammar_num].grammar;
    else
        *active_grammar = NULL;
    }



static void srec_test_get_active_grammar_data ( ApplicationData *data, APPL_GRAMMAR_DATA **active_grammar_data )
    {

    if ( data->active_grammar_num >= 0 )
        *active_grammar_data = &data->grammars [data->active_grammar_num];
    else
        *active_grammar_data = NULL;
    }



static ESR_BOOL srec_test_get_grammar_from_id ( ApplicationData *data, char *grammar_id,
                                            int *grammar_index, ESR_BOOL *is_active, ESR_BOOL *is_ve_grammar )
    {
    ESR_BOOL            found_grammar;
    int             grammar_counter;

    found_grammar = ESR_FALSE;
    grammar_counter = 0;

    while ( ( found_grammar == ESR_FALSE ) && ( grammar_counter < data->grammarCount ) )
        {
        if ( strcmp ( grammar_id, data->grammars [grammar_counter].grammarID ) == 0 )
            {
            *grammar_index = grammar_counter;
            *is_ve_grammar = data->grammars [grammar_counter].is_ve_grammar;

            if ( grammar_counter == data->active_grammar_num )
                *is_active = ESR_TRUE;
            else
                *is_active = ESR_FALSE;
            found_grammar = ESR_TRUE;
            }
        else
            {
            grammar_counter++;
            }
        }
    return ( found_grammar );
    }



static int srec_test_get_empty_grammar_index ( ApplicationData *data, unsigned int *grammar_index )
    {
    int get_status;

    if ( data->grammarCount < MAX_NUM_REC_CONTEXTS )
        {
        get_status = 0;
        *grammar_index = data->grammarCount;
        }
    else
        {
        get_status = -1;
        }
    return ( get_status );
    }



ESR_ReturnCode ShutdownSession ( void )
    {
    ESR_ReturnCode    shutdown_status;

    shutdown_status = SR_SessionDestroy ( );

    return ( shutdown_status );
    }



ESR_ReturnCode InitSession ( int argc, char** argv )
    {
    ESR_ReturnCode    init_status;
    LCHAR             path[P_PATH_MAX];
    size_t            len;

    len = P_PATH_MAX;
    init_status = ESR_CommandLineGetValue ( argc, (const char **)argv, L("parfile"), path, &len );

    if ( init_status == ESR_SUCCESS )
        {
        init_status = SR_SessionCreate ( path );

        if ( init_status == ESR_SUCCESS )
            {
  /* Command-line options always override PAR file options */
            init_status = ESR_SessionImportCommandLine ( argc, argv );

            if ( init_status != ESR_SUCCESS )
                {
                SR_SessionDestroy ( );
                /* Log Here */
                }
            }
        else
            {
            /* Log Here */
            }
        }
    else
        {
        srec_test_log_error ( 0, ERROR_LEVEL_CRITICAL, L("Parfile Nmae Not Specified on Command Line") );
        }
    return ( init_status );
    }



ESR_ReturnCode ShutdownGrammarUnload ( ApplicationData *data, unsigned int grammar_num )
    {
    ESR_ReturnCode  shutdown_status;

    shutdown_status = SR_GrammarDestroy ( data->grammars [grammar_num].grammar );

    return ( shutdown_status );
    }



ESR_ReturnCode SetupGrammarLoad ( ApplicationData *data, unsigned int grammar_num )
    {
    ESR_ReturnCode  setup_status;

    setup_status = SR_GrammarLoad (data->grammars [grammar_num].grammar_path, &data->grammars [grammar_num].grammar );

    if ( setup_status == ESR_SUCCESS )
        {
        setup_status = SR_GrammarSetupVocabulary ( data->grammars [grammar_num].grammar, data->vocabulary );

        if ( setup_status == ESR_SUCCESS )
            {
            // setup_status = SR_GrammarSetupModels ( data->grammars [grammar_num].grammar, data->models );
            setup_status = SR_GrammarSetupRecognizer( data->grammars [grammar_num].grammar, data->recognizer );

            if ( setup_status == ESR_SUCCESS )
                {
                setup_status = SR_GrammarSetDispatchFunction ( data->grammars [grammar_num].grammar, L("myDSMCallback"), NULL, myDSMCallback );

                if ( setup_status != ESR_SUCCESS )
                    SR_GrammarDestroy ( data->grammars [grammar_num].grammar );
                }
            else
                {
                SR_GrammarDestroy ( data->grammars [grammar_num].grammar );
                }
            }
        else
            {
            SR_GrammarDestroy ( data->grammars [grammar_num].grammar );
            }
        }
    return ( setup_status );
    }



ESR_ReturnCode SetupGrammarActivate ( ApplicationData *data, unsigned int grammar_num )
    {
    ESR_ReturnCode  setup_status;

	setup_status = SR_RecognizerActivateRule ( data->recognizer, data->grammars [grammar_num].grammar, data->grammars [grammar_num].ruleName, 1 );
    return ( setup_status );
    }



#ifdef ACCURACY_TESTING
ESR_ReturnCode srec_test_parse (SR_Grammar *grammar, const LCHAR* trans, LCHAR* meaning, size_t *len);
#endif

/**
 * Parses source string and copies the first whitespace-delimited token into destination.
 *
 * @param source Source string to parse
 * @param target Target string to copy into
 * @param charsRead [in] Size of target buffer.
 *                  [out] Number of characters read up to end of token.
 *                  If the return code is ESR_BUFFER_OVERFLOW, the required length is
 *                  returned in this variable.
 */
int getFirstToken(LCHAR* source, LCHAR* target, size_t* charsRead)
{
  LCHAR* beginning = source;
  LCHAR* ending;

  /* Skip whitespace */
  for (; *beginning!=L('\0') && LISSPACE(*beginning); ++beginning);
  if (*beginning==L('\0'))
    return ( -1 ); /* invalid command syntax */
  /* Find next whitespace */
  for (ending=beginning; *ending!=L('\0') && !LISSPACE(*ending); ++ending);
  if ((size_t) (ending-beginning) > *charsRead)
  {
    *charsRead = ending-beginning;
    return ( -1 );
  }
  *charsRead = ending-source;
  LSTRNCPY(target, beginning, ending-beginning);
  target[ending-beginning] = L('\0');
  return ( 0 );
}



int srec_test_get_five_command_items ( LCHAR *command_start, size_t first_max_command_size, LCHAR *first_command,
                                       size_t second_max_command_size, LCHAR *second_command,
                                       size_t third_max_command_size, LCHAR *third_command,
                                       size_t fourth_max_command_size, LCHAR *fourth_command,
                                       size_t fifth_max_command_size, LCHAR *fifth_command,
                                       size_t *actual_commands, LCHAR **command_end )
    {
    int get_status;

    get_status = getFirstToken ( command_start, first_command, &first_max_command_size );

    if ( get_status == ESR_SUCCESS )
        {
        get_status = getFirstToken ( command_start + first_max_command_size, second_command, &second_max_command_size );

        if ( get_status == ESR_SUCCESS )
            {
            get_status = getFirstToken ( command_start + first_max_command_size + second_max_command_size,
                                         third_command, &third_max_command_size );
            if ( get_status == ESR_SUCCESS )
                {
                get_status = getFirstToken ( command_start + first_max_command_size + second_max_command_size + third_max_command_size,
                                             fourth_command, &fourth_max_command_size );
                if ( get_status == ESR_SUCCESS )
                    {
                    get_status = getFirstToken ( command_start + first_max_command_size + second_max_command_size + third_max_command_size + fourth_max_command_size,
                                                 fifth_command, &fifth_max_command_size );
                    if ( get_status == ESR_SUCCESS )
                        {
                        if ( command_end != NULL )
                            *command_end = command_start + first_max_command_size + second_max_command_size + third_max_command_size + fourth_max_command_size + fifth_max_command_size;
                        if ( actual_commands != NULL )
                            *actual_commands = 5;
                        }
                    else
                        {
                        if ( command_end != NULL )
                            *command_end = command_start + first_max_command_size + second_max_command_size + third_max_command_size + fourth_max_command_size;
                        if ( actual_commands != NULL )
                            *actual_commands = 4;
                        }
                    }
                else
                    {
                    if ( command_end != NULL )
                        *command_end = command_start + first_max_command_size + second_max_command_size + third_max_command_size;
                    if ( actual_commands != NULL )
                        *actual_commands = 3;
                    }
                }
            else
                {
                if ( command_end != NULL )
                    *command_end = command_start + first_max_command_size + second_max_command_size;
                if ( actual_commands != NULL )
                    *actual_commands = 2;
                }
            }
        else
            {
            if ( command_end != NULL )
                *command_end = command_start + first_max_command_size;
            if ( actual_commands != NULL )
                *actual_commands = 1;
            }
        }
    else
        {
        if ( command_end != NULL )
            *command_end = command_start;
        if ( actual_commands != NULL )
            *actual_commands = 0;
        }
    return ( get_status );
    }



int srec_test_get_four_command_items ( LCHAR *command_start, size_t first_max_command_size, LCHAR *first_command,
                                       size_t second_max_command_size, LCHAR *second_command,
                                       size_t third_max_command_size, LCHAR *third_command,
                                       size_t fourth_max_command_size, LCHAR *fourth_command,
                                       size_t *actual_commands, LCHAR **command_end )
    {
    int get_status;

    get_status = getFirstToken ( command_start, first_command, &first_max_command_size );

    if ( get_status == ESR_SUCCESS )
        {
        get_status = getFirstToken ( command_start + first_max_command_size, second_command, &second_max_command_size );

        if ( get_status == ESR_SUCCESS )
            {
            get_status = getFirstToken ( command_start + first_max_command_size + second_max_command_size,
                                         third_command, &third_max_command_size );
            if ( get_status == ESR_SUCCESS )
                {
                get_status = getFirstToken ( command_start + first_max_command_size + second_max_command_size + third_max_command_size,
                                             fourth_command, &fourth_max_command_size );
                if ( get_status == ESR_SUCCESS )
                    {
                    if ( command_end != NULL )
                        *command_end = command_start + first_max_command_size + second_max_command_size + third_max_command_size + fourth_max_command_size;
                    if ( actual_commands != NULL )
                        *actual_commands = 4;
                    }
                else
                    {
                    if ( command_end != NULL )
                        *command_end = command_start + first_max_command_size + second_max_command_size + third_max_command_size;
                    if ( actual_commands != NULL )
                        *actual_commands = 3;
                    }
                }
            else
                {
                if ( command_end != NULL )
                    *command_end = command_start + first_max_command_size + second_max_command_size;
                if ( actual_commands != NULL )
                    *actual_commands = 2;
                }
            }
        else
            {
            if ( command_end != NULL )
                *command_end = command_start + first_max_command_size;
            if ( actual_commands != NULL )
                *actual_commands = 1;
            }
        }
    else
        {
        if ( command_end != NULL )
            *command_end = command_start;
        if ( actual_commands != NULL )
            *actual_commands = 0;
        }
    return ( get_status );
    }



int srec_test_get_three_command_items ( LCHAR *command_start, size_t first_max_command_size, LCHAR *first_command,
                                        size_t second_max_command_size, LCHAR *second_command,
                                        size_t third_max_command_size, LCHAR *third_command,
                                        size_t *actual_commands, LCHAR **command_end )
    {
    int get_status;

    get_status = getFirstToken ( command_start, first_command, &first_max_command_size );

    if ( get_status == ESR_SUCCESS )
        {
        get_status = getFirstToken ( command_start + first_max_command_size, second_command, &second_max_command_size );

        if ( get_status == ESR_SUCCESS )
            {
            get_status = getFirstToken ( command_start + first_max_command_size + second_max_command_size,
                                         third_command, &third_max_command_size );
            if ( get_status == ESR_SUCCESS )
                {
                if ( command_end != NULL )
                    *command_end = command_start + first_max_command_size + second_max_command_size + third_max_command_size;
                if ( actual_commands != NULL )
                    *actual_commands = 3;
                }
            else
                {
                if ( command_end != NULL )
                    *command_end = command_start + first_max_command_size + second_max_command_size;
                if ( actual_commands != NULL )
                    *actual_commands = 2;
                }
            }
        else
            {
            if ( command_end != NULL )
                *command_end = command_start + first_max_command_size;
            if ( actual_commands != NULL )
                *actual_commands = 1;
            }
        }
    else
        {
        if ( command_end != NULL )
            *command_end = command_start;
        if ( actual_commands != NULL )
            *actual_commands = 0;
        }
    return ( get_status );
    }



int srec_test_get_two_command_items ( LCHAR *command_start, size_t first_max_command_size, LCHAR *first_command,
                                      size_t second_max_command_size, LCHAR *second_command,
                                      size_t *actual_commands, LCHAR **command_end )
    {
    int get_status;

    get_status = getFirstToken ( command_start, first_command, &first_max_command_size );

    if ( get_status == ESR_SUCCESS )
        {
        get_status = getFirstToken ( command_start + first_max_command_size, second_command, &second_max_command_size );

        if ( get_status == ESR_SUCCESS )
            {
            if ( command_end != NULL )
                *command_end = command_start + first_max_command_size + second_max_command_size;
            if ( actual_commands != NULL )
                *actual_commands = 2;
            }
        else
            {
            if ( command_end != NULL )
                *command_end = command_start + first_max_command_size;
            if ( actual_commands != NULL )
                *actual_commands = 1;
            }
        }
    else
        {
        if ( command_end != NULL )
            *command_end = command_start;
        if ( actual_commands != NULL )
            *actual_commands = 0;
        }
    return ( get_status );
    }



int srec_test_get_one_command_item ( LCHAR *command_start, size_t max_command_size, LCHAR *command, LCHAR **command_end )
    {
    int get_status;

    get_status = getFirstToken ( command_start, command, &max_command_size );

    if ( get_status == ESR_SUCCESS )
        {
        if ( command_end != NULL )
            *command_end = command_start + max_command_size;
        }
    return ( get_status );
    }



/**
 * Execute TCP-file commands.
 *
 * @param text String containing command
 * @param recognizer The recognizer
 */
//static int words_added = 0;

#if defined(APP_ENABLE_TIMER)
static PTimer *addWordTimer = NULL;
static PTimer *compileTimer = NULL;
#endif



int srec_test_reset_slots ( SR_Grammar *active_grammar )
    {
    int             reset_status;
    ESR_ReturnCode  esr_status;

    if ( active_grammar != NULL )
        {
        reset_status = 0;
        esr_status = SR_GrammarResetAllSlots ( active_grammar );

        if ( esr_status != ESR_SUCCESS )
            {
            reset_status = -1;
            /* Log Here */
            }
        }
    else
        {
        reset_status = -1;
        /* Log Here */
        }
    return ( reset_status );
    }



int srec_test_add_word ( SR_Grammar *active_grammar, LCHAR *command_text )
    {
    int             add_status;
    ESR_ReturnCode  esr_status;
    LCHAR           slot [MAX_LINE_LENGTH];
    LCHAR           word [MAX_LINE_LENGTH];
    LCHAR           pron [MAX_LINE_LENGTH];
    LCHAR           weight [MAX_UINT_DIGITS+1];
    LCHAR           semanticTag [MAX_LINE_LENGTH];
    int             weightNumber;
    int             convert_string_to_num;

    if ( active_grammar != NULL )
        {
        add_status  = srec_test_get_five_command_items ( command_text, MAX_LINE_LENGTH, slot,
                                                         MAX_LINE_LENGTH, word, MAX_LINE_LENGTH, pron,
                                                         MAX_UINT_DIGITS + 1, weight, MAX_LINE_LENGTH,
                                                         semanticTag, NULL, NULL );
        if ( add_status == 0 )
            {
            convert_string_to_num = lstrtoi (weight, &weightNumber, 10 );

            if ( convert_string_to_num == 0 )
                {
#if defined(APP_ENABLE_TIMER)
                PTimerStart ( addWordTimer );
#endif
                esr_status = SR_GrammarAddWordToSlot ( active_grammar, slot, word, pron, weightNumber, semanticTag );
#if defined(APP_ENABLE_TIMER)
                PTimerStop(addWordTimer);
#endif
                if ( esr_status != ESR_SUCCESS )
                    {
                    add_status = -1;
                    /* Log Here */
                    }
                }
            else
                {
                add_status = -1;
                /* Log Here */
                }
            }
        else
            {
            add_status = -1;
            /* Log Here */
            }
        }
    else
        {
        add_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_MODERATE, "No Grammar Activated" );
        }
    return ( add_status );
    }



int srec_test_compile_active_context ( SR_Grammar *active_grammar )
    {
    int             compile_status;
    ESR_ReturnCode  esr_status;

    if ( active_grammar != NULL )
        {
        compile_status = 0;
#if defined(APP_ENABLE_TIMER)
        PTimerStart ( compileTimer );
#endif
        esr_status = SR_GrammarCompile( active_grammar );
#if defined(APP_ENABLE_TIMER)
        PTimerStop ( compileTimer );
#endif
        if ( esr_status != ESR_SUCCESS )
            {
            compile_status = -1;
            /* Log Here */
            }
        }
    else
        {
        compile_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_MODERATE, L("No Active Grammar To Compile") );
        }
    return ( compile_status );
    }



int srec_test_load_grammar_data_from_command ( ApplicationData *data, unsigned int grammar_num, LCHAR *command_text )
    {
    int             get_status;
    ESR_ReturnCode  esr_status;
    LCHAR           path [P_PATH_MAX];
    LCHAR           id [P_PATH_MAX];
    LCHAR           rule [P_PATH_MAX];
    LCHAR           ve_marker [P_PATH_MAX];
    size_t          path_length;

    get_status = srec_test_get_four_command_items ( command_text, P_PATH_MAX, path, P_PATH_MAX, id,
                                                    P_PATH_MAX, rule, P_PATH_MAX, ve_marker, NULL, NULL );
    if ( get_status == 0 )
        {
        path_length = P_PATH_MAX;
        esr_status = ESR_SessionPrefixWithBaseDirectory ( path, &path_length );

        if ( esr_status == ESR_SUCCESS )
            {
            LSTRCPY ( data->grammars [grammar_num].grammar_path, path );
            LSTRCPY ( data->grammars [grammar_num].grammarID, id );
            LSTRCPY ( data->grammars [grammar_num].ruleName, rule );

            if ( LSTRCMP ( ve_marker, L("ve") ) ==0 )
                data->grammars [grammar_num].is_ve_grammar = ESR_TRUE;
            else if ( LSTRCMP ( ve_marker, L("not_ve") ) ==0 )
                data->grammars [grammar_num].is_ve_grammar = ESR_FALSE;
            else
                {
                get_status = -1;
                /* Log Here */
                }
            }
        else
            {
            get_status = -1;
            /* Log Here */
            }
        }
    else
        {
        /* Log Here */
        }
    return ( get_status );
    }



int srec_test_load_context ( ApplicationData *data, LCHAR *command_text )
    {
    int             load_status;
    ESR_ReturnCode  esr_status;
    unsigned int    open_grammar;

    load_status = srec_test_get_empty_grammar_index ( data, &open_grammar );

    if ( load_status == 0 )
        {
        load_status = srec_test_load_grammar_data_from_command ( data, open_grammar, command_text );

        if ( load_status == 0 )
            {
            esr_status = SetupGrammarLoad ( data, open_grammar );

            if ( esr_status == ESR_SUCCESS )
                {
                data->grammarCount++;
                }
            else
                {
                load_status = -1;
                /* Log Here */
                }
            }
        else
            {
            /* Log Here */
            }
        }
    else
        {
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, L("Maximum Number Of Grammars Already Loaded") );
        }
    return ( load_status );
    }



int srec_test_free_context ( SR_Grammar *active_grammar, ApplicationData *data, LCHAR *command_text )
    {
    int             free_status;
    ESR_ReturnCode  esr_status;
    int             grammar_num;
    ESR_BOOL            found_grammar;
    ESR_BOOL            grammar_is_active;
    ESR_BOOL            grammar_is_ve;
    LCHAR           grammar_id [P_PATH_MAX];

    free_status = srec_test_get_one_command_item ( command_text, P_PATH_MAX, grammar_id, NULL );

    if ( free_status == 0 )
        {
        found_grammar = srec_test_get_grammar_from_id ( data, grammar_id, &grammar_num, &grammar_is_active, &grammar_is_ve );

        if ( found_grammar == ESR_TRUE )
            {
            if ( grammar_is_active == ESR_TRUE )
                {
                if ( grammar_is_ve == ESR_TRUE )
                    {
                    esr_status = SR_RecognizerSetBoolParameter ( data->recognizer, L("enableGetWaveform"), ESR_FALSE );

                    if ( esr_status != ESR_SUCCESS )
                        {
                        free_status = -1;
                        /* Log Here */
                        }
                    }
                else
                    {
                    esr_status = ESR_SUCCESS;
                    }
                if ( esr_status == ESR_SUCCESS )
                    {
                    esr_status = SR_RecognizerDeactivateRule ( data->recognizer, data->grammars [data->active_grammar_num].grammar,
                                                               data->grammars [data->active_grammar_num].ruleName );
                    if ( esr_status == ESR_SUCCESS )
                        {
						data->active_grammar_num = -1;
                        }
                    else
                        {
                        free_status = -1;
                        /* Log Here */
                        }
                    }
                }
            else
                {
                free_status = -1;
                /* Log Here */
                }
            }
        else
            {
            free_status = -1;
            /* Log Here */
            }
        }
    else
        {
        /* Log Here */
        }
    return ( free_status );
    }



int srec_test_unload_context ( ApplicationData *data, LCHAR *command_text )
    {
    int             unload_status;
    ESR_ReturnCode  esr_status;
    int             grammar_num;
    ESR_BOOL            found_grammar;
    ESR_BOOL            grammar_is_active;
    ESR_BOOL            grammar_is_ve;
    LCHAR           grammar_id [P_PATH_MAX];

   unload_status = srec_test_get_one_command_item ( command_text, P_PATH_MAX, grammar_id, NULL );

   if ( unload_status == 0 )
        {
        found_grammar = srec_test_get_grammar_from_id ( data, grammar_id, &grammar_num, &grammar_is_active, &grammar_is_ve );

        if ( found_grammar == ESR_TRUE )
            {
            if ( grammar_is_active == ESR_FALSE )
                {
                esr_status = SR_GrammarDestroy ( data->grammars [grammar_num].grammar );

                if ( esr_status != ESR_SUCCESS )
                    {
                    unload_status = -1;
                    /* Log Here */
                    }
                srec_test_delete_grammar ( data, grammar_num );
                }
            else
                {
                unload_status = -1;
                /* Log Here */
                }
            }
        else
            {
            unload_status = -1;
            /* Log Here */
            }
            }
    else
        {
        /* Log Here */
        }
    return ( unload_status );
    }



int srec_test_use_context ( SR_Grammar *active_grammar, ApplicationData *data, LCHAR *command_text )
    {
    int             use_status;
    ESR_ReturnCode  esr_status;
    int             grammar_num;
    ESR_BOOL            found_grammar;
    ESR_BOOL            grammar_is_active;
    ESR_BOOL            grammar_is_ve;
    LCHAR           grammar_id [P_PATH_MAX];

    if ( active_grammar == NULL )
        {
        use_status = srec_test_get_one_command_item ( command_text, P_PATH_MAX, grammar_id, NULL );

        if ( use_status == 0 )
            {
            found_grammar = srec_test_get_grammar_from_id ( data, grammar_id, &grammar_num, &grammar_is_active, &grammar_is_ve );

            if ( found_grammar == ESR_TRUE )
                {
                    esr_status = SR_RecognizerActivateRule ( data->recognizer, data->grammars [grammar_num].grammar,
                                                             data->grammars [grammar_num].ruleName, 1 );
                    if ( esr_status == ESR_SUCCESS )
                        {
                        if ( data->grammars [grammar_num].is_ve_grammar == ESR_TRUE )
                            {
                            esr_status = SR_RecognizerSetBoolParameter ( data->recognizer, L("enableGetWaveform"), ESR_TRUE );

                            if ( esr_status == ESR_SUCCESS )
                                {
                                data->active_grammar_num = (int)grammar_num;
                                }
                            else
                                {
                                use_status = -1;
                                /* Log Here */
                                SR_RecognizerDeactivateRule ( data->recognizer, data->grammars [grammar_num].grammar,
                                                              data->grammars [grammar_num].ruleName );
                                }
                            }
                        else
                            {
                            data->active_grammar_num = (int)grammar_num;
                            }
                        }
                    else
                        {
                        use_status = -1;
                        /* Log Here */
                        }
                }
            else
                {
                use_status = -1;
                /* Log Here */
                }
            }
        else
            {
            use_status = -1;
            /* Log Here */
            }
        }
    else
        {
         use_status = -1;
        /* Log Here */
        }
    return ( use_status );
    }



int srec_test_save_context ( SR_Grammar *active_grammar, LCHAR *command_text )
    {
    int             save_status;
    ESR_ReturnCode  esr_status;
    LCHAR           file_name [P_PATH_MAX];

    if ( active_grammar != NULL )
        {
        save_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, file_name, NULL );

        if ( save_status == 0 )
            {
            esr_status = SR_GrammarSave ( active_grammar, file_name );

            if ( esr_status != ESR_SUCCESS )
                {
                save_status = -1;
                /* Log Here */
                }
            }
        else
            {
            /* Log Here */
            }
        }
    else
        {
        save_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_MODERATE, "No Grammar Activated" );
        }
    return ( save_status );
    }



int srec_test_voice_enroll ( SR_Grammar *active_grammar, ApplicationData *data, LCHAR *command_text )
    {
    int             enroll_status;
    ESR_ReturnCode  esr_status;
    LCHAR           slot [P_PATH_MAX];
    LCHAR           nametagID [P_PATH_MAX];
    LCHAR           weight [MAX_UINT_DIGITS+1];
    int             weightNumber;
    int             convert_string_to_num;

    if ( active_grammar != NULL )
        {
        if ( data->nametag != NULL )
            {
            enroll_status = srec_test_get_three_command_items ( command_text, P_PATH_MAX, slot, P_PATH_MAX, nametagID,
                                                                MAX_UINT_DIGITS + 1, weight, NULL, NULL );
            if ( enroll_status == 0 )
                {
                convert_string_to_num = lstrtoi ( weight, &weightNumber, 10 );

                if ( convert_string_to_num == 0 )
                    {
                    esr_status = SR_NametagSetID ( data->nametag, nametagID );

                    if ( esr_status == ESR_SUCCESS )
                        {
                        esr_status = SR_GrammarAddNametagToSlot ( active_grammar, slot, data->nametag, weightNumber, NULL );

                        if ( esr_status != ESR_SUCCESS )
                            {
                            enroll_status = -1;
                            /* Log Here */
                            }
                        }
                    else
                        {
                        enroll_status = -1;
                        /* Log Here */
                        }
                    }
                else
                    {
                    enroll_status = -1;
                    /* Log Here */
                    }
                }
            else
                {
                /* Log Here */
                }
            }
        else
            {
            enroll_status = -1;
            /* Log Here */
            }
        }
    else
        {
        enroll_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_MODERATE, "No Grammar Activated" );
        }
    return ( enroll_status );
    }



int srec_test_load_nametags ( ApplicationData *data, LCHAR *command_text )
    {
    int             load_status;
    ESR_ReturnCode  esr_status;
    LCHAR           file_name [P_PATH_MAX];

    load_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, file_name, NULL );

    if ( load_status == 0 )
        {
        esr_status = SR_NametagsLoad ( data->nametags, file_name );

        if ( esr_status != ESR_SUCCESS )
            {
            load_status = -1;
            /* Log Here */
            }
        }
    else
        {
        load_status = -1;
        /* Log Here */
        }
    return ( load_status );
    }



int srec_test_save_nametags ( ApplicationData *data, LCHAR *command_text )
    {
    int             save_status;
    ESR_ReturnCode  esr_status;
    LCHAR           file_name [P_PATH_MAX];

    save_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, file_name, NULL );

    if ( save_status == 0 )
        {
        esr_status = SR_NametagsSave ( data->nametags, file_name );

        if ( esr_status != ESR_SUCCESS )
            {
            save_status = -1;
            /* Log Here */
            }
        }
    else
        {
        save_status = -1;
        /* Log Here */
        }
    return ( save_status );
    }



int srec_test_clear_nametags ( ApplicationData *data )
    {
    int             clear_status;
    ESR_ReturnCode  esr_status;

    clear_status = 0;
    esr_status = SR_NametagsDestroy ( data->nametags );

    if ( esr_status == ESR_SUCCESS )
        {
        data->nametags = NULL;
        esr_status = SR_NametagsCreate ( &data->nametags );

        if ( esr_status != ESR_SUCCESS )
            {
            clear_status = -1;
            /* Log Here */
            }
        }
    else
        {
        clear_status = -1;
        /* Log Here */
        }
    return ( clear_status );
    }



int srec_test_add_to_nametags ( ApplicationData *data, LCHAR *command_text )
    {
    int             add_status;
    ESR_ReturnCode  esr_status;
    LCHAR           nametagID [P_PATH_MAX];

    if ( data->nametag != NULL )
        {
        add_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, nametagID, NULL );

        if ( add_status == 0 )
            {
            esr_status = SR_NametagSetID ( data->nametag, nametagID );

            if ( esr_status == ESR_SUCCESS )
                {
                esr_status = SR_NametagsAdd ( data->nametags, data->nametag );

                if ( esr_status == ESR_SUCCESS )
                    {
                    data->nametag = NULL;
                    }
                else
                    {
                    add_status = -1;
                    /* Log Here */
                    }
                }
            else
                {
                add_status = -1;
                /* Log Here */
                }
            }
        else
            {
            add_status = -1;
            /* Log Here */
            }
        }
    else
        {
        add_status = -1;
        /* Log Here */
        }
    return ( add_status );
    }


int srec_test_voice_enroll_nametags ( SR_Grammar *active_grammar, ApplicationData *data, LCHAR *command_text )
  {
    int             enroll_status;
    ESR_ReturnCode  esr_status;
    LCHAR           slot [P_PATH_MAX];
    SR_Nametag      *nametag;
    size_t          nametags_size;
    size_t          current_nametag;

    if ( active_grammar != NULL )
        {
        enroll_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, slot, NULL );

        if ( enroll_status == 0 )
            {
            esr_status = SR_NametagsGetSize (data->nametags, &nametags_size );

            if ( esr_status == ESR_SUCCESS )
                {
                current_nametag = 0;

                while ( ( current_nametag < nametags_size ) && ( esr_status == ESR_SUCCESS ) )
                    {
                    esr_status = SR_NametagsGetAtIndex ( data->nametags, current_nametag, &nametag );

                    if ( esr_status == ESR_SUCCESS )
                        {
                        esr_status = SR_GrammarAddNametagToSlot ( active_grammar, slot, nametag, 0, NULL );

                        if ( esr_status == ESR_SUCCESS )
                            {
                            current_nametag++;
                            }
                        else
                            {
                            enroll_status = -1;
                            /* Log Here */
                            }
                        }
                    else
                        {
                        enroll_status = -1;
                        /* Log Here */
                        }
                    }
                }
            else
                {
                enroll_status = -1;
                /* Log Here */
                }
            }
        else
            {
            /* Log Here */
            }
        }
    else
        {
        enroll_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_MODERATE, "No Grammar Activated" );
        }
    return ( enroll_status );
    }



int srec_test_load_acousticstate ( ApplicationData *data, LCHAR *command_text )
    {
    int             load_status;
    ESR_ReturnCode  esr_status;
    LCHAR           file_name [P_PATH_MAX];

    load_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, file_name, NULL );

    if ( load_status == 0 )
        {
        esr_status = SR_AcousticStateLoad ( data->recognizer, file_name );

        if ( esr_status != ESR_SUCCESS )
            {
            load_status = -1;
            /* Log Here */
            }
        }
    else
        {
        /* Log Here */
        }
    return ( load_status );
    }



int srec_test_reset_acousticstate ( ApplicationData *data )
    {
    int             reset_status;
    ESR_ReturnCode  esr_status;

    reset_status = 0;
    esr_status = SR_AcousticStateReset ( data->recognizer );

    if ( esr_status != ESR_SUCCESS )
        {
        reset_status = -1;
        /* Log Here */
        }
    return ( reset_status );
    }



int srec_test_set_forced_rec_mode ( ApplicationData *data, LCHAR *command_text )
    {
    int         set_status;
    LCHAR       mode[P_PATH_MAX];

    set_status =  srec_test_get_one_command_item ( command_text, P_PATH_MAX, mode, NULL );

    if ( set_status == 0 )
        {
        if ( LSTRCMP ( mode, L("one_time") ) == 0 )
            {
            data->forced_rec_mode = ForcedRecModeOneTime;
            }
        else if ( LSTRCMP ( mode, L("off") ) == 0 )
            {
            data->forced_rec_mode = ForcedRecModeOff;
            }
        else if ( LSTRCMP ( mode, L("on") ) == 0 )
            {
            data->forced_rec_mode = ForcedRecModeOn;
            }
        else
            {
            set_status = -1;
            /* Log Here */
            }
        }
    return ( set_status );
    }



int srec_test_execute_command ( ApplicationData *data, AUDIOIN_H audio_input_handle, LCHAR *text, FILE *results_file, size_t *recognition_count )
    {
    int         execute_status;
    LCHAR       *current_command_start;
    LCHAR       *current_end_command;
    LCHAR       command [MAX_LINE_LENGTH];
    SR_Grammar  *active_grammar;
    LCHAR       log_buffer [LOG_BUFFER_SIZE];

    srec_test_get_active_grammar ( data, &active_grammar );
    current_command_start = text;
    execute_status = srec_test_get_one_command_item ( current_command_start, MAX_LINE_LENGTH, command, &current_end_command );

    if ( execute_status == 0 )
        {
		if( data->nametag 
			&& ((LSTRCMP(command, "recognize_nist")==0) || (LSTRCMP(command, "recognize_pcm")==0)) ) {
				/* if there is a nametag held in memory, and we don't make use of it, then
				let's destroy it here */  
			SR_NametagDestroy(  data->nametag);
			data->nametag = NULL;
		}
        if ( LSTRCMP ( command, L("recognize_live") ) == 0 )
            execute_status = srec_test_recognize_live ( active_grammar, data, audio_input_handle, results_file, recognition_count );
        else if ( LSTRCMP ( command, L("context_load") ) == 0 )
            execute_status = srec_test_load_context ( data, current_end_command );
        else if ( LSTRCMP ( command, L("context_use") ) == 0 )
            execute_status = srec_test_use_context ( active_grammar, data, current_end_command );
        else if ( LSTRCMP ( command, L("context_free") ) == 0 )
            execute_status = srec_test_free_context ( active_grammar, data, current_end_command );
        else if ( LSTRCMP ( command, L("context_unload") ) == 0 )
            execute_status = srec_test_unload_context ( data, current_end_command );
        else if ( LSTRCMP ( command, L("addwords_from_nametags") ) == 0 )
            execute_status = srec_test_voice_enroll_nametags ( active_grammar, data, current_end_command );
        else if ( LSTRCMP ( command, L("resetslots") ) == 0 )
            execute_status = srec_test_reset_slots ( active_grammar );
        else  if ( LSTRCMP ( command, L("addword") ) == 0 )
            execute_status = srec_test_add_word ( active_grammar, current_end_command );
        else if ( LSTRCMP ( command, L("context_compile") ) == 0 )
            execute_status = srec_test_compile_active_context ( active_grammar );
        else if ( LSTRCMP ( command, L("context_save") ) == 0 )
            execute_status = srec_test_save_context ( active_grammar, current_end_command );
        else if ( LSTRCMP ( command, L("addword_from_last_nametag") ) == 0 )
            execute_status = srec_test_voice_enroll ( active_grammar, data, current_end_command );
        else if ( LSTRCMP ( command, L("load_nametags") ) == 0 )
            execute_status = srec_test_load_nametags ( data, current_end_command );
        else if ( LSTRCMP ( command, L("save_nametags") ) == 0 )
            execute_status = srec_test_save_nametags ( data, current_end_command );
        else if ( LSTRCMP ( command, L("clear_nametags") ) ==0 )
            execute_status = srec_test_clear_nametags ( data );
        else if ( LSTRCMP ( command, L("add_to_nametags") ) == 0 )
            execute_status = srec_test_add_to_nametags ( data, current_end_command );
        else if ( LSTRCMP ( command, L("acousticstate_load") ) == 0 )
            execute_status = srec_test_load_acousticstate ( data, current_end_command );
        else if ( LSTRCMP ( command, L("acousticstate_reset") ) == 0 )
            execute_status = srec_test_reset_acousticstate ( data );
        else if ( LSTRCMP ( command, L("forced_rec") ) == 0 )
            execute_status = srec_test_set_forced_rec_mode ( data, current_end_command );
        else if ( *( command ) == L('#') )
            execute_status = 0;   /* Comment in file just skip */
        else
            {
            execute_status = -1;
            LSPRINTF ( log_buffer, L("Unknown Command %s"), command );
            srec_test_log_error ( 0, ERROR_LEVEL_MODERATE, log_buffer );
            }
        }
    else
        {
        /* Log Here */
        }
    return ( execute_status );
    }



int srec_test_open_command_file ( PFile **command_file )
    {
    int             open_status;
    ESR_ReturnCode  esr_status;
    LCHAR           file_name [P_PATH_MAX];
    size_t          len;

    open_status = 0;
    len = P_PATH_MAX;
    esr_status = ESR_SessionGetLCHAR ( L("cmdline.tcp"), file_name, &len );

    if ( esr_status == ESR_SUCCESS )
        {
        len = P_PATH_MAX;
        esr_status = ESR_SessionPrefixWithBaseDirectory ( file_name, &len );

        if ( esr_status == ESR_SUCCESS )
            {
	    *command_file = pfopen ( file_name,  L("r") );

	    if ( ( *command_file ) == NULL )
                {
                open_status = -1;
                /* Log Here */
                }
            }
        else
            {
            open_status = -1;
            /* Log Here */
            }
        }
     else
         {
         open_status = -1;
         /* Log Here */
         }
     return ( open_status );
     }



void srec_test_close_command_file ( PFile *command_file )
    {

    pfclose ( command_file );
    }



void srec_test_close_audio_file ( PFile *audio_file )
    {

    pfclose ( audio_file );
    }



int srec_test_open_results_file ( FILE **results_file )
    {
    int             open_status;
    ESR_ReturnCode  esr_status;
    LCHAR           file_name [P_PATH_MAX];
    size_t          len;

    open_status = 0;
    len = P_PATH_MAX;
    esr_status = ESR_SessionGetLCHAR ( L("cmdline.results"), file_name, &len );

    if ( esr_status == ESR_SUCCESS )
        {
        *results_file = fopen ( file_name, L("w") );

        if ( ( *results_file ) == NULL )
            {
            open_status = -1;
            /* Log Here */
            }
        }
     else
         {
         open_status = -1;
         /* Log Here */
         }
     return ( open_status );
     }



void srec_test_close_results_file ( FILE *results_file )
    {

    fclose ( results_file );
    }



int srec_test_process_commands ( ApplicationData *data, AUDIOIN_H audio_input_handle )
    {
    int             process_status;
    PFile           *command_file;
    FILE            *results_file;
    LCHAR           *got_line_ok;
    LCHAR           linebuffer [MAX_LINE_LENGTH];
    size_t          recognition_count;

    recognition_count = 0;
    process_status = srec_test_open_command_file ( &command_file );

    if ( process_status == 0 )
        {
        process_status = srec_test_open_results_file ( &results_file );

        if ( process_status == 0 )
            {
            do
                {
                got_line_ok = pfgets ( linebuffer, MAX_LINE_LENGTH, command_file );

                if ( got_line_ok != NULL )
                    srec_test_execute_command ( data, audio_input_handle, linebuffer, results_file, &recognition_count );
                }
            while ( ( got_line_ok != NULL ) && ( process_status == 0 ) );
			if( data->nametag ) {
				SR_NametagDestroy(  data->nametag);
				data->nametag = NULL;
			}

            srec_test_close_results_file ( results_file );
            }
        srec_test_close_command_file ( command_file );
        }
    return ( process_status );
    }



int srec_test_open_nist_file ( LCHAR *file_name, PFile **nist_file )
    {
    int             open_status;
    ESR_ReturnCode  esr_status;
    int             lstr_result;
    LCHAR           file_path [P_PATH_MAX];
    size_t          len;

    open_status = 0;
    len = P_PATH_MAX;
    esr_status = ESR_SessionGetLCHAR ( L("cmdline.datapath"), file_path, &len );

    if ( esr_status == ESR_SUCCESS )
        {
        len = P_PATH_MAX;
        esr_status = ESR_SessionPrefixWithBaseDirectory ( file_path, &len );

        if ( esr_status == ESR_SUCCESS )
            {
            esr_status = pf_convert_backslashes_to_forwardslashes ( file_path );

            if ( esr_status == ESR_SUCCESS )
                {
                len = P_PATH_MAX;
                lstr_result = lstrinsert ( file_path, file_name, 0, &len );

                if ( lstr_result == 0 )
                    {
		    *nist_file = pfopen ( file_name, L("rb") );

                    if ( ( *nist_file ) != NULL )
                        {
                        esr_status = pfseek ( *nist_file, 1024, SEEK_SET );

                        if ( esr_status != ESR_SUCCESS )
                            {
                            open_status = -1;
                            /* Log Here */
                            }
                        }
                    else
                        {
                        open_status = -1;
                        /* Log Here */
                        }
                    }
                else
                    {
                    open_status = -1;
                    /* Log Here */
                    }
                }
            else
                {
                open_status = -1;
                /* Log Here */
                }
            }
        else
            {
            open_status = -1;
            /* Log Here */
            }
        }
     else
         {
         open_status = -1;
         /* Log Here */
         }
     return ( open_status );
     }



int srec_test_get_audio_from_file ( PFile *audio_file, ApplicationData *data, ESR_BOOL *hit_eof )
    {
    int get_status;
    int eof_status;

    get_status = 0;
    data->num_samples_read = pfread ( data->audio_buffer, sizeof ( asr_int16_t ), data->audio_buffer_requested_size, audio_file );

    if ( data->num_samples_read > 0 )
        {
        *hit_eof = ESR_FALSE;
        }
    else
        {
        eof_status = pfeof ( audio_file );

        if ( eof_status == 0 )
            {
            get_status = -1;
            /* Log Here */
            }
        else
            {
            *hit_eof = ESR_TRUE;
            }
        }
    return ( get_status );
    }



int srec_test_feed_recognizer ( ApplicationData *data, ESR_BOOL hit_eof, SR_RecognizerStatus *esr_recog_status, SR_RecognizerResultType *result_type )
    {
    int             feed_status;
    ESR_ReturnCode  esr_status;

    feed_status = 0;
    esr_status = SR_RecognizerPutAudio ( data->recognizer, data->audio_buffer, &data->num_samples_read, hit_eof );

    if ( esr_status == ESR_SUCCESS )
        {
        do
            {
            esr_status = SR_RecognizerAdvance ( data->recognizer, esr_recog_status, result_type, &data->result );

            if ( esr_status != ESR_SUCCESS )
                {
                feed_status = -1;
                *esr_recog_status = SR_RECOGNIZER_EVENT_STOPPED;
                *result_type = SR_RECOGNIZER_RESULT_TYPE_COMPLETE;
                /* Log Here */
                }
            }
        while ( ( *esr_recog_status ) == SR_RECOGNIZER_EVENT_INCOMPLETE );
        }
    else
        {
        feed_status = -1;
        /* Log Here */
        }
     return ( feed_status );
     }



int srec_test_flush_audio ( ApplicationData *data, SR_RecognizerStatus *esr_recog_status, SR_RecognizerResultType *result_type )
    {
    int             flush_status;
    ESR_ReturnCode  esr_status;

    flush_status = 0;

    while ( ( *result_type ) != SR_RECOGNIZER_RESULT_TYPE_COMPLETE )
        {
        esr_status = SR_RecognizerAdvance ( data->recognizer, esr_recog_status, result_type, &data->result );

        if ( esr_status != ESR_SUCCESS )
            {
            flush_status = -1;
            *esr_recog_status = SR_RECOGNIZER_EVENT_STOPPED;
            *result_type = SR_RECOGNIZER_RESULT_TYPE_COMPLETE;
            /* Log Here */
            }
        }
    return ( flush_status );
    }



int srec_test_process_start_timeout ( ApplicationData *data, FILE *results_file )
    {
    int             process_status;
    ESR_ReturnCode  esr_status;
    size_t          utterance_timeout;

    process_status = 0;
    esr_status = ESR_SessionGetSize_t ( L("SREC.Recognizer.utterance_timeout"), &utterance_timeout );

    if ( esr_status == ESR_SUCCESS )
        {
        LFPRINTF ( results_file, L("E: utterance_timeout %lu\n"), (unsigned long)utterance_timeout );
        LFPRINTF ( results_file, L("R: <FAILED>\n") );
        LPRINTF ( L("\n-------------------------------------\n") );
        LPRINTF ( L("E: utterance_timeout %lu\n"), (unsigned long)utterance_timeout );
        LPRINTF ( L("R: <FAILED>\n") );
        LPRINTF ( L("-------------------------------------\n\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    srec_test_log_recognition_failure ( data );

    return ( process_status );
    }


int srec_test_write_and_log_wave_form_file ( ApplicationData *data, size_t recognition_count )
    {
    int                 write_status;
    ESR_ReturnCode      esr_status;
    LCHAR               *wave_filename;

    write_status = 0;
    LSPRINTF ( data->raw_waveform_filename, L("a%lu__%s.raw"), (unsigned long)recognition_count, data->transcription );
    wave_filename = data->raw_waveform_filename;

    while ( *wave_filename )
        {
        if ( *wave_filename == ' ')
            *wave_filename = '_';
        wave_filename++;
        }
/* just write to file for now... for testing purposes */
    LPRINTF ( L("Dumping audio waveform to file %s\n"), data->raw_waveform_filename );
    data->raw_waveform_file = pfopen ( data->raw_waveform_filename, L("wb") );

    if ( data->raw_waveform_file != NULL )
        {
        pfwrite ( (void*)data->raw_waveform, 1, data->raw_waveform_size, data->raw_waveform_file );
        pfclose ( data->raw_waveform_file );
/* log the filename in the ESR log */
        esr_status = SR_RecognizerLogToken ( data->recognizer, "WVFMFILENAME", data->raw_waveform_filename );

        if( esr_status != ESR_SUCCESS )
            {
            write_status = -1;
            /* Log Here */
            }
        }
    else
        {
        write_status = -1;
        /* Log Here */
        }
    return ( write_status );
    }



int srec_test_process_nbest_list ( ApplicationData *data, FILE *results_file )
    {
    int                 process_status;
    ESR_ReturnCode      esr_status;
    size_t              nbestSize;
    size_t              nbest_num;
    LCHAR               linebuffer [MAX_LINE_LENGTH];
    size_t              line_length;

    process_status = 0;
      /* At least one semantic result exists */
    LPRINTF ( L("\n\n----------------------------------------------\n") );
    line_length =  MAX_LINE_LENGTH;
    esr_status = SR_RecognizerResultGetValue ( data->result, 0, L("conf"), linebuffer, &line_length );

    if ( esr_status == ESR_SUCCESS )
        {
        LPRINTF ( L("CONFIDENCE SCORE : '%s'\n"), linebuffer );
        LPRINTF ( L("TRANSCRIPTION    : '%s'\n"), data->transcription );
        esr_status = SR_RecognizerResultGetSize (data->result, &nbestSize );

        if ( esr_status == ESR_SUCCESS )
            {
            for ( nbest_num = 0; nbest_num < nbestSize; nbest_num++ )
                {
                line_length =  MAX_LINE_LENGTH;
                esr_status = SR_RecognizerResultGetValue ( data->result, nbest_num, L("literal"), linebuffer, &line_length );

                if ( esr_status == ESR_SUCCESS )
                    {
                    LPRINTF ( L("LITERAL[%2lu]      : '%s'\n"), (unsigned long)nbest_num, linebuffer );
                    line_length = MAX_LINE_LENGTH;
                    esr_status = SR_RecognizerResultGetValue ( data->result, nbest_num, L("meaning"), linebuffer, &line_length );

                    if ( esr_status != ESR_SUCCESS )
                        {
                        linebuffer [0] = L('\0') ;
                        }
                    LPRINTF ( L("MEANING[%2lu]      : '%s'\n"), (unsigned long)nbest_num, linebuffer );
                    line_length = MAX_LINE_LENGTH;
                    esr_status = SR_RecognizerResultGetValue (data->result, nbest_num, L("raws"), linebuffer, &line_length );

                    if ( esr_status == ESR_SUCCESS )
                        {
                            LPRINTF ( L("RAW SCORE[%2lu]    : '%s'\n\n"), (unsigned long)nbest_num, linebuffer);
                        }
                    else
                        {
                        process_status = -1;
                        /* Log Here */
                        }
                    }
                else
                    {
                    process_status = -1;
                    /* Log Here */
                    }
                }
            }
        else
            {
            process_status = -1;
            /* Log Here */
            }
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    LPRINTF ( L("----------------------------------------------\n\n") );
    return ( process_status );
    }



int srec_test_process_recognition ( ApplicationData *data, FILE *results_file, size_t recognition_count )
    {
    int                 process_status;
    ESR_ReturnCode      esr_status;
    APPL_GRAMMAR_DATA   *grammar_data;
    LCHAR               linebuffer [MAX_LINE_LENGTH];
    size_t              line_length;

    process_status = 0;
    srec_test_get_active_grammar_data ( data, &grammar_data );
    line_length = MAX_LINE_LENGTH;
    esr_status = SR_RecognizerResultGetValue ( data->result, 0, L("literal"), linebuffer, &line_length );

    if ( esr_status == ESR_SUCCESS )
        {
        LFPRINTF ( results_file, L("R: %s\n"), linebuffer );
        line_length = MAX_LINE_LENGTH;
        esr_status = SR_RecognizerResultGetValue ( data->result, 0, L("conf"), linebuffer, &line_length );

        if ( esr_status == ESR_SUCCESS )
            {
            LFPRINTF ( results_file, L("S: %s\n"), linebuffer);
            LPRINTF ( L("S: %s\n"), linebuffer);
            srec_test_process_nbest_list ( data, results_file );
         /*
          * SR_RecognizerResultGetWaveform will return pointer to buffer holding
          * audio data in it. This buffer is NOT under the application's control
          * and MUST only be read from.
          */
            if ( grammar_data->is_ve_grammar == ESR_TRUE )
                {
                LPRINTF ( L("VoiceEnrollement=>SUCCESS\n") );
                esr_status = SR_NametagCreate ( data->result, L("dummyID"), &data->nametag );

                if ( esr_status == ESR_SUCCESS )
                    {
                    esr_status = SR_RecognizerResultGetWaveform ( data->result, &data->raw_waveform, &data->raw_waveform_size );

                    if( esr_status == ESR_SUCCESS )
                        {
                        if ( data->raw_waveform )
                            {
                            process_status = srec_test_write_and_log_wave_form_file ( data, recognition_count );

                            if ( process_status == 0 )
                                {
                                esr_status = SR_RecognizerLogEvent ( data->recognizer, "ESRve" );

                                if( esr_status != ESR_SUCCESS )
                                    {
                                    process_status = -1;
                                    /* Log Here */
                                    }
                                }
                            else
                                {
                                /* Log Here */
                                }
                            }
                        }
                    else
                        {
                        process_status = -1;
                        /* Log Here */
                        }
                    }
                else
                    {
                    process_status = -1;
                    /* Log Here */
                    }
                }
            }
        else
            {
            process_status = -1;
            /* Log Here */
            }
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    return ( process_status );
    }



int srec_test_process_recognition_fail ( ApplicationData *data )
    {
    int                 process_status;
    ESR_ReturnCode      esr_status;
    APPL_GRAMMAR_DATA   *grammar_data;
    ESR_BOOL                reason_status;

    process_status = 0;
    srec_test_get_active_grammar_data ( data, &grammar_data );
    LPRINTF(L("*** no match in recognition***\n"));

    if ( grammar_data->is_ve_grammar == ESR_TRUE )
        {
        data->nametag = NULL;
        LPRINTF ( L("VoiceEnrollement = FAILED : \n") );
        }
    esr_status = SR_RecognizerIsSignalClipping ( data->recognizer, &reason_status );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( reason_status == ESR_TRUE )
            LPRINTF ( L("- Signal is clipping\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    esr_status = SR_RecognizerIsSignalDCOffset ( data->recognizer, &reason_status );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( reason_status == ESR_TRUE )
            LPRINTF ( L("- Signal is DC-offset\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    esr_status = SR_RecognizerIsSignalNoisy ( data->recognizer, &reason_status );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( reason_status == ESR_TRUE )
            LPRINTF ( L("- Signal is noisy\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    esr_status = SR_RecognizerIsSignalTooFewSamples ( data->recognizer, &reason_status );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( reason_status == ESR_TRUE )
            LPRINTF ( L("- Signal has too few samples\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    esr_status = SR_RecognizerIsSignalTooManySamples ( data->recognizer, &reason_status );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( reason_status == ESR_TRUE )
            LPRINTF ( L("- Signal has too many samples\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    esr_status = SR_RecognizerIsSignalTooQuiet ( data->recognizer, &reason_status );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( reason_status == ESR_TRUE )
            LPRINTF ( L("- Signal is too quiet\n") );
        }
    else
        {
        process_status = -1;
        /* Log Here */
        }
    srec_test_log_recognition_failure ( data );
    return ( process_status );
    }



int srec_test_process_recognition_unsupported_case ( ApplicationData *data, FILE *results_file )
    {
    int process_status;

    process_status = 0;
    LFPRINTF ( results_file, L("E: No results available\n") );
    LFPRINTF ( results_file, L("R: <FAILED>\n") );
    srec_test_log_recognition_failure ( data );

    return ( process_status );
    }



static void srec_test_log_recognition_failure ( ApplicationData *data )
    {

    LPRINTF(L("----------------------------------------------\n"));
    LPRINTF(L("TRANSCRIPTION    : '%s'\n"), data->transcription);
    LPRINTF(L("<NO-RESULTS>\n"));
    LPRINTF(L("----------------------------------------------\n\n"));
    }



int srec_test_process_results ( ApplicationData *data, SR_RecognizerStatus esr_recog_status,
                                FILE *results_file, size_t recognition_count )
    {
    int process_status;

    switch ( esr_recog_status )
        {
        case SR_RECOGNIZER_EVENT_START_OF_UTTERANCE_TIMEOUT:
            process_status = srec_test_process_start_timeout ( data, results_file );
            break;

        case SR_RECOGNIZER_EVENT_RECOGNITION_RESULT:
            process_status = srec_test_process_recognition ( data, results_file, recognition_count );
            break;

        case SR_RECOGNIZER_EVENT_NO_MATCH:
            process_status = srec_test_process_recognition_fail ( data );
            break;

        default:
            process_status = srec_test_process_recognition_unsupported_case ( data, results_file );
            break;
        }
    return ( process_status );
    }



int srec_test_log_reco_from_file_data ( SR_Grammar *active_grammar, ApplicationData *data, LCHAR *waveform, LCHAR *bos, LCHAR *eos, LCHAR *transcription )
    {
    int             log_status;
    ESR_ReturnCode  esr_status;
    size_t          result_count;
    ESR_BOOL            got_results;
    size_t          transcription_length;

    log_status = 0;
    LSPRINTF ( data->transcription, "%s", transcription );
    transcription_length = LSTRLEN ( data->transcription );

    while ( ( *( data->transcription + transcription_length - 1 ) == '\n' ) ||
            ( *( data->transcription + transcription_length - 1 ) == '\r' ) )
        {
        *( data->transcription + transcription_length - 1 ) = '\0';
        transcription_length--;
        }
    LPRINTF ( L("D: %s\nC: %s\n"), waveform, data->transcription );
    esr_status = SR_GrammarCheckParse ( active_grammar, data->transcription, 0, &result_count );

    if ( esr_status == ESR_SUCCESS )
        {
        if ( result_count > 0 )
            {
            got_results = ESR_TRUE;
            LPRINTF ( L("Sem (%lu):  invocab=1\n"), (unsigned long)result_count );
            }
        else
            {
            got_results = ESR_FALSE;
            LPRINTF ( L("Sem:  <NO INTERPRETATION FOUND>\n") );
            }
        esr_status = SR_RecognizerLogWaveformData ( data->recognizer, waveform, data->transcription, atof ( bos ), atof ( eos ), got_results );

        if ( esr_status != ESR_SUCCESS )
            {
            log_status = -1;
            /* Log Here */
            }
        }
    else
        {
        log_status = -1;
        /* Log Here */
        }
    return ( log_status );
    }



int srec_test_start_audio ( AUDIOIN_H audio_input_handle )
    {
    int                     start_status;
    LHS_AUDIOIN_ERROR       audio_status;

    start_status = 0;
    audio_status = lhs_audioinStart ( audio_input_handle );

    if ( audio_status == LHS_AUDIOIN_OK )
        {
        LPRINTF ( L("\n!!!!!! Start Speaking !!!!!!....\n") );
        }
    else
        {
        start_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_CRITICAL, "Audio Device Failed To Start" );
        }
    return ( start_status );
    }



int srec_test_stop_audio ( AUDIOIN_H audio_input_handle )
    {
    int                     stop_status;
    LHS_AUDIOIN_ERROR       audio_status;

    stop_status = 0;
    audio_status = lhs_audioinStop ( audio_input_handle );

    if ( audio_status == LHS_AUDIOIN_OK )
        {
        LPRINTF ( L("\n!!!!!! Audio Stopped !!!!!!....\n") );
        }
    else
        {
        stop_status = -1;
        /* Log Here */
        }
    return ( stop_status );
    }


int srec_test_get_audio_from_live_input ( ApplicationData *data, AUDIOIN_H audio_input_handle, ESR_BOOL *hit_eof )
    {
    int                     get_status;
    LHS_AUDIOIN_ERROR       audio_status;
    AUDIOIN_INFO            input_status;
    unsigned long data__num_samples_read;

    get_status = 0;
    *hit_eof = ESR_FALSE;
    data->num_samples_read = data->audio_buffer_requested_size;
    data__num_samples_read = data->num_samples_read;
    audio_status = lhs_audioinGetSamples ( audio_input_handle, &data__num_samples_read, data->audio_buffer, &input_status );
    data->num_samples_read = (unsigned  int)data__num_samples_read;

    if ( audio_status == LHS_AUDIOIN_OK )
        {
        if ( data->num_samples_read == 0 )
            *hit_eof = ESR_TRUE;
        }
    else
        {
        get_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, "Audio Device Failed To Read" );
        }
    return ( get_status );
    }



static int srec_test_recognize_live ( SR_Grammar *active_grammar, ApplicationData *data, AUDIOIN_H audio_input_handle, FILE *results_file, size_t *recognition_count )
    {
    int                     recognize_status;
    ESR_ReturnCode          esr_status;
    SR_RecognizerStatus     esr_recog_status;
    SR_RecognizerResultType result_type;
    ESR_BOOL                    hit_eof;

    if ( active_grammar != NULL )
        {
        recognize_status = srec_test_start_audio ( audio_input_handle );

        if ( recognize_status == 0 )
            {
            if ( ( data->forced_rec_mode == ForcedRecModeOn ) || ( data->forced_rec_mode == ForcedRecModeOneTime ) )
                SR_GrammarAllowOnly ( active_grammar, data->transcription );
            esr_status = SR_RecognizerStart ( data->recognizer );

            if ( esr_status == ESR_SUCCESS )
                {
                ( *recognition_count )++;
                hit_eof = ESR_FALSE;

                do
                    {
                    recognize_status = srec_test_get_audio_from_live_input ( data, audio_input_handle, &hit_eof );

                    if ( recognize_status == 0 )
                        recognize_status = srec_test_feed_recognizer ( data, hit_eof, &esr_recog_status, &result_type  );
                    }
                while ( ( hit_eof == ESR_FALSE ) && ( result_type != SR_RECOGNIZER_RESULT_TYPE_COMPLETE ) && ( recognize_status == 0 ) );

                if ( recognize_status == 0 )
                    {
                    recognize_status = srec_test_flush_audio ( data, &esr_recog_status, &result_type );

                    if ( recognize_status == 0 )
                        {
                        recognize_status = srec_test_process_results ( data, esr_recog_status, results_file, *recognition_count );
                        }
                    }
                }
                esr_status = SR_RecognizerStop ( data->recognizer );

                if (esr_status == ESR_SUCCESS )
                    {
                    LPRINTF ( L("Recognizer has been stopped\n") );
                    }
                else
                    {
                    recognize_status = -1;
                    LPRINTF ( L("Recognizer has failed to stop\n") );
                    }
            if ( data->forced_rec_mode == ForcedRecModeOneTime )
                {
                data->forced_rec_mode = ForcedRecModeOff;
                SR_GrammarAllowAll ( active_grammar );
                }
            srec_test_stop_audio ( audio_input_handle );
            }
        }
     else
         {
         recognize_status = -1;
         /* Log Here */
         }
     return ( recognize_status );
     }



#define STACK_SIZE (1024 * 200)

#ifdef _WIN32
/* disable optimization for the next functions as the compiler optimizes away the assignment to mySTACK[i] */
#pragma optimize("", off)

static void initStack()
{
  int mySTACK[STACK_SIZE];
 {
   /* This extra block is to ensure that local variables of the function occur after buffer mySTACK. */
   int i;

   for (i = 0; i < STACK_SIZE; ++i)
   {
     mySTACK[i] = 0xDEADBEEF;
   }
 }
}

static int analyzeStack()
{
  int mySTACK[STACK_SIZE];
 {

   /* This extra block is to ensure that local variables of the function occur after buffer mySTACK. */
   int i, j;

   for (i = STACK_SIZE - 1; i >= 0; --i)
   {
     if (mySTACK[i] == 0xDEADBEEF)
     {
       /* This might be a candidate for the end of stack marker, or it could be
          some value that is equal to our marker.  To ensure reliability of
          this candidate, we will make sure that all remaining entries int the
          stack are also equal to DEADBEEF.
       */
       for (j = i - 1; j >= 0; --j)
       {
         if (mySTACK[j] != 0xDEADBEEF)
         {
           i = j;
           break;
         }
       }
       if (j < 0) break;
     }
   }

   if (i < 0)
     return -1;
   else
     return (STACK_SIZE - 1 - i) * sizeof(int);
 }
}

/* restore optmization settings to what they used to be. */
#pragma optimize("", on)
#endif


#ifdef ACCURACY_TESTING
static void srec_test_clean_up_sentence ( char* sentence )
    {
    int                         clean_up_status;
    int                         sentence_finished;
    SENTENCE_CLEANING_STATES    current_state;
    char                        *current_input;
    char                        *current_output;

    clean_up_status = 0;
    sentence_finished = 0;
    current_state = SENTENCE_BEGIN;
    current_input = sentence;
    current_output = sentence;

    do
        {
        switch ( *current_input )
            {
            case '\0':
                switch ( current_state )
                    {
                    case SENTENCE_BEGIN:
                        break;

                    case SENTENCE_BEGIN_BRACKET_BEGIN:  /* Is this error condition */
                        *current_output = '\0';
                        clean_up_status = -1;
                        break;

                    case SENTENCE_BEGIN_BRACKET_END:
                        *current_output = '\0';
                        break;

                    case SENTENCE_MIDDLE:
                        *current_output = '\0';
                        break;

                    case SENTENCE_MIDDLE_BRACKET_BEGIN: /* Is this error condition */
                        *( current_output - 1 ) = '\0';
                        clean_up_status = -1;
                        break;

                    case SENTENCE_MIDDLE_BRACKET_END:
                        *( current_output - 1 ) = '\0';
                        break;

                    case SENTENCE_MIDDLE_WITH_SPACE:
                        *( current_output - 1 ) = '\0';
                        break;

                    default:
                        *current_output = '\0';
                        /* Log error */
                        break;
                    }
                sentence_finished = 1;
                break;

            case ' ':
                switch ( current_state )
                    {
                    case SENTENCE_BEGIN:
                        break;

                    case SENTENCE_BEGIN_BRACKET_BEGIN:
                        break;

                    case SENTENCE_BEGIN_BRACKET_END:
                        break;

                    case SENTENCE_MIDDLE:
                        *current_output = ' ';
                        current_output++;
                        current_state = SENTENCE_MIDDLE_WITH_SPACE;
                        break;

                    case SENTENCE_MIDDLE_BRACKET_BEGIN: /* Is this error condition */
                        break;

                    case SENTENCE_MIDDLE_BRACKET_END:
                        break;

                    case SENTENCE_MIDDLE_WITH_SPACE:
                        break;

                    default:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;
                    }
                current_input++;
                break;

            case '[':
                switch ( current_state )
                    {
                    case SENTENCE_BEGIN:
                        current_state = SENTENCE_BEGIN_BRACKET_BEGIN;
                        break;

                    case SENTENCE_BEGIN_BRACKET_BEGIN:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    case SENTENCE_BEGIN_BRACKET_END:
                        current_state = SENTENCE_BEGIN_BRACKET_BEGIN;
                        break;

                    case SENTENCE_MIDDLE:
                        *current_output = ' ';
                        current_output++;
                        current_state = SENTENCE_MIDDLE_BRACKET_BEGIN;
                        break;

                    case SENTENCE_MIDDLE_BRACKET_BEGIN: /* Is this error condition */
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    case SENTENCE_MIDDLE_BRACKET_END:
                        current_state = SENTENCE_MIDDLE_BRACKET_BEGIN;
                        break;

                    case SENTENCE_MIDDLE_WITH_SPACE:
                        current_state = SENTENCE_MIDDLE_BRACKET_BEGIN;
                        break;

                    default:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;
                    }
                current_input++;
                break;

            case ']':
                switch ( current_state )
                    {
                    case SENTENCE_BEGIN:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    case SENTENCE_BEGIN_BRACKET_BEGIN:
                        current_state = SENTENCE_BEGIN_BRACKET_END;
                        break;

                    case SENTENCE_BEGIN_BRACKET_END:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    case SENTENCE_MIDDLE:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    case SENTENCE_MIDDLE_BRACKET_BEGIN: /* Is this error condition */
                        current_state = SENTENCE_MIDDLE_BRACKET_END;
                        break;

                    case SENTENCE_MIDDLE_BRACKET_END:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    case SENTENCE_MIDDLE_WITH_SPACE:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;

                    default:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;
                    }
                current_input++;
                break;

            default:
                switch ( current_state )
                    {
                    case SENTENCE_BEGIN:
                        *current_output = *current_input;
                        current_output++;
                        current_state = SENTENCE_MIDDLE;
                        break;

                    case SENTENCE_BEGIN_BRACKET_BEGIN:
                        break;

                    case SENTENCE_BEGIN_BRACKET_END:
                        *current_output = *current_input;
                        current_output++;
                        current_state = SENTENCE_MIDDLE;
                        break;

                    case SENTENCE_MIDDLE:
                        *current_output = *current_input;
                        current_output++;
                        current_state = SENTENCE_MIDDLE;
                        break;

                    case SENTENCE_MIDDLE_BRACKET_BEGIN:
                        break;

                    case SENTENCE_MIDDLE_BRACKET_END:
                        *current_output = *current_input;
                        current_output++;
                        current_state = SENTENCE_MIDDLE;
                        break;

                    case SENTENCE_MIDDLE_WITH_SPACE:
                        *current_output = *current_input;
                        current_output++;
                        current_state = SENTENCE_MIDDLE;
                        break;

                    default:
                        *current_output = '\0';
                        clean_up_status = -1;
                        /* Log error */
                        break;
                    }
                current_input++;
                break;
            }
        }
    while ( ( sentence_finished == 0 ) && ( clean_up_status == 0 ) );
    }



ESR_ReturnCode srec_test_parse ( SR_Grammar* grammar, const LCHAR* trans, LCHAR* meaning, size_t *len )
    {
    ESR_ReturnCode      parse_status;
    char                cleaned_trans[TRANSCRIPTION_SIZE];
    SR_SemanticResult   *semanticResults;
    size_t              result_count;

    result_count = 0;
    strcpy( cleaned_trans, trans );
    srec_test_clean_up_sentence ( cleaned_trans );

  /* create the result holders, initially not greater than MAX */
    parse_status = SR_SemanticResultCreate ( &semanticResults );

    if ( parse_status == ESR_SUCCESS )
        {
        result_count = 1;
        parse_status = SR_SemanticProcessor_Flush( ( (SR_GrammarImpl*)grammar )->semproc );

        if ( parse_status == ESR_SUCCESS )
            {
            parse_status = SR_SemanticProcessor_SetParam( ((SR_GrammarImpl*)grammar)->semproc, L("literal"), cleaned_trans );

            if ( parse_status == ESR_SUCCESS )
                {
                parse_status = grammar->checkParse ( grammar, cleaned_trans, &semanticResults, (size_t*)&result_count );

                if ( parse_status == ESR_SUCCESS )
                    {
                    if ( result_count < 1 )
                        {
                        LSTRCPY ( meaning, L("") );
                        SR_SemanticResultDestroy( semanticResults);
                        parse_status = ESR_NO_MATCH_ERROR;
                        }
                    else
                        {
                        parse_status = semanticResults->getValue ( semanticResults, "meaning", meaning, len);
                        SR_SemanticResultDestroy( semanticResults);
                        }
                    }
                }
            }
        }
    return ( parse_status );
    }
#endif


static int srec_test_get_run_params ( unsigned int *num_shutdown_loops, unsigned int *num_continuous_run_loops )
    {
    int get_status;

    get_status = get_num_srec_test_shutdown_times ( num_shutdown_loops );

    if ( get_status == 0 )
                get_status = get_num_srec_test_continuous_loops ( num_continuous_run_loops );

    return ( get_status );
    }



static int srec_test_shutdown_application_data ( ApplicationData *applicationData )
    {
    int init_status;
    int i;

    init_status = 0;

    applicationData->argc = 0;
    applicationData->argv = NULL;
    applicationData->outputLog = PSTDOUT;       // may need to check if non PSTDOUT or non PSTDERROR
    applicationData->locale = -1;

    if (applicationData->recognizer != NULL)
        {
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, L("Failed To Cleanup Recognizer") );
/*        SR_RecognizerLogSessionEnd ( applicationData->recognizer );
        SR_RecognizerDestroy ( applicationData->recognizer );*/
        applicationData->recognizer = NULL;
        applicationData->result = NULL;                 // this was deallocated by SR_RecognizerDestroy()
        }

    if (applicationData->vocabulary != NULL)
        {
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, L("Failed To Cleanup Vocabulary") );
/*        SR_VocabularyDestroy(applicationData->vocabulary);
        applicationData->vocabulary = NULL;*/
        }


    if (applicationData->nametag != NULL)
        {
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, L("Failed To Cleanup NameTag") );
/*        SR_NametagDestroy(applicationData->nametag);
        applicationData->nametag = NULL;*/
        }

    if (applicationData->nametags != NULL)
        {
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, L("Failed To Cleanup NameTagSet") );
/*        SR_NametagsDestroy(applicationData->nametags);
        applicationData->nametags = NULL;*/
        }

    for (i = 0; i < applicationData->grammarCount; ++i)
        srec_test_log_error ( 0, ERROR_LEVEL_HIGH, L("Failed To Cleanup Grammar") );
/*
        if ( applicationData->grammars [i] != NULL )
            {
            printf ( "!!!!!!!!  %d Grammars Not Destroyed !!!!!!!!!!!!\n", i );
            SR_GrammarDestroy(applicationData->grammars[i]);
            applicationData->grammars[i] = NULL;
            }
        }

    applicationData->activeGrammar = -1;
    applicationData->activeRule = NULL;
    applicationData->voiceEnrollment = NULL;
*/
    applicationData->raw_waveform = NULL;
    applicationData->raw_waveform_filename [0] = L( '\0' );
    applicationData->raw_waveform_file = NULL;
    applicationData->transcription[0] = L( '\0' );
    applicationData->forced_rec_mode = ForcedRecModeNotSet;

    return ( init_status );
    }



static int srec_test_init_application_data ( ApplicationData *applicationData, int arg_count, LCHAR *arg_vals [] )
    {
    int init_status;

    init_status = 0;
    applicationData->argc = arg_count;
    applicationData->argv = arg_vals;
    applicationData->outputLog = PSTDOUT;
    applicationData->locale = -1;
    applicationData->recognizer = NULL;
    applicationData->result = NULL;
    applicationData->vocabulary = NULL;
    applicationData->nametag = NULL;
    applicationData->nametags = NULL;
    applicationData->grammarCount = 0;  /* No need to initialize arrays, index is 0 */
    applicationData->active_grammar_num = -1;
/*    applicationData->activeRule = NULL;
    applicationData-> = applicationData->voiceEnrollment = NULL;*/
    applicationData->audio_buffer_requested_size = DEFAULT_AUDIO_BUFFER_SIZE;
    applicationData->raw_waveform = NULL;
    applicationData->raw_waveform_filename [0] = L( '\0' );
    applicationData->raw_waveform_file = NULL;
    applicationData->transcription[0] = L( '\0' );
    applicationData->forced_rec_mode = ForcedRecModeNotSet;
    return ( init_status );
    }


static int srec_test_run_test_shutdown_session ( ApplicationData *applicationData )
    {
    int shutdown_status;

    shutdown_status = 0;

    SR_RecognizerUnsetup ( applicationData->recognizer); // releases acoustic models
    SR_RecognizerDestroy ( applicationData->recognizer );
    applicationData->recognizer = NULL;
    ShutdownSession ( );

    return ( shutdown_status );
    }



static int srec_test_run_test_init_session ( ApplicationData *applicationData )
{
  int             run_status;
  ESR_ReturnCode  esr_status;
  
  run_status = 0;
  LPRINTF(L("\nCreate recognizer:\n"));
  LPRINTF(L("    InitSession()\n"));
  esr_status = InitSession ( applicationData->argc, applicationData->argv );
  
  if ( esr_status == ESR_SUCCESS )
    {
      LPRINTF(L("    SR_RecognizerCreate()\n"));
      esr_status = SR_RecognizerCreate ( &applicationData->recognizer );
      
      if ( esr_status != ESR_SUCCESS )
	{
	  ShutdownSession ( );
	  run_status = -1;
	  /* Log Here */
	} else {
	  LPRINTF(L("    SR_RecognizerSetup()\n"));
	  esr_status = SR_RecognizerSetup ( applicationData->recognizer); 
	  if ( esr_status != ESR_SUCCESS )
	    {
	      ShutdownSession ( );
	      run_status = -1;
	      /* Log Here */
	    }
	} 
    }
  return ( run_status );
}


static int srec_test_run_test_shutdown_vocab_grammar ( ApplicationData *applicationData )
    {
    int shutdown_status;

    shutdown_status = 0;
    SR_RecognizerLogSessionEnd ( applicationData->recognizer );
/*    SR_GrammarDestroy ( applicationData->grammars [0].grammar );
    applicationData->grammars [0].grammar = NULL;*/
    SR_VocabularyDestroy ( applicationData->vocabulary );
    applicationData->vocabulary = NULL;

    return ( shutdown_status );
    }



static int srec_test_run_test_init_vocab_grammar ( ApplicationData *applicationData )
    {
    int             run_status;
    ESR_ReturnCode  esr_status;
    LCHAR           filename[P_PATH_MAX];
    size_t          len;

    run_status = 0;
   /* Create vocabulary object and associate with grammar */
    LPRINTF(L("Create vocabulary object and associate with grammar:\n"));
    len = P_PATH_MAX;
    esr_status = ESR_SessionGetLCHAR ( L("cmdline.vocabulary"), filename, &len );

    if ( esr_status == ESR_SUCCESS )
        {
        LPRINTF(L("    SR_VocabularyLoad()\n"));
        esr_status = SR_VocabularyLoad ( filename, &applicationData->vocabulary );

        if ( esr_status == ESR_SUCCESS )
            {
            LPRINTF(L("    SR_VocabularyGetLanguage()\n"));
            esr_status =  SR_VocabularyGetLanguage ( applicationData->vocabulary, &applicationData->locale );

            if ( esr_status == ESR_SUCCESS )
                {
                /* start a new log session */
                LPRINTF( L("Start a new log session:\n") );
                LPRINTF( L("    SR_RecognizerLogSessionStart()\n") );
                esr_status = SR_RecognizerLogSessionStart ( applicationData->recognizer, L("SRecTest.session1") );

                if ( esr_status != ESR_SUCCESS )
                    {
                    SR_VocabularyDestroy ( applicationData->vocabulary );
                    applicationData->vocabulary = NULL;
                    run_status = -1;
                    /* Log here */
                    }
                }
            else
                {
                SR_VocabularyDestroy ( applicationData->vocabulary );
                applicationData->vocabulary = NULL;
                run_status = -1;
                /* Log Here */
                }
            }
        else
            {
            run_status = -1;
            /* Log Here */
            }
        }
    else
        {
        run_status = -1;
        /* Log Here */
        }
    return ( run_status );
    }



static int srec_test_run_test_shutdown ( ApplicationData *applicationData )
    {
    int shutdown_status;

    shutdown_status = srec_test_run_test_shutdown_vocab_grammar ( applicationData );

    if ( shutdown_status == 0 )
        {
            shutdown_status = srec_test_run_test_shutdown_session ( applicationData );
        }
    return ( shutdown_status );
    }


static int srec_test_run_test_init ( ApplicationData *applicationData )
{
  int run_status;
  
  run_status = srec_test_run_test_init_session ( applicationData );
  
  if ( run_status == 0 )
    {
      run_status = srec_test_run_test_init_vocab_grammar ( applicationData );
      
      if ( run_status != 0 )
	{
	  srec_test_run_test_shutdown_session ( applicationData );
	}
    } 
  else
    {
      srec_test_run_test_shutdown_session ( applicationData );
    }
  return ( run_status );
}


static int srec_test_run_test_execute ( ApplicationData *applicationData, AUDIOIN_H audio_input_handle )
    {
    int             run_status;
    ESR_ReturnCode  esr_status;

    run_status = 0;
    applicationData->nametag = NULL;

    LPRINTF(L("Recognize:\n"));
    LPRINTF(L("    SR_NametagsCreate()\n"));
    esr_status = SR_NametagsCreate ( &applicationData->nametags );

    if ( esr_status == ESR_SUCCESS )
        {
        run_status = srec_test_process_commands ( applicationData, audio_input_handle );
        SR_NametagsDestroy ( applicationData->nametags );
        applicationData->nametags = NULL;

        if ( run_status != 0 )
            {
            /* Log Here */
            }
        }
    else
        {
        run_status = -1;
        /* Log Here */
        }
    return ( run_status );
    }



static int srec_test_run_test ( ApplicationData *applicationData, AUDIOIN_H audio_input_handle )
    {
    int run_status;

    run_status = srec_test_run_test_init ( applicationData );

    if ( run_status == 0 )
        {
        run_status = srec_test_run_test_execute ( applicationData, audio_input_handle );
        srec_test_run_test_shutdown ( applicationData );
        }
    return ( run_status );
    }



static int srec_test_shutdown_memory_system ( void )
    {
    int shutdown_status;

    shutdown_status = 0;
    PMemShutdown ( );

    return ( shutdown_status );
    }



static int srec_test_init_memory_system ( unsigned int srec_test_heap_size )
    {
    int             init_status;
    ESR_ReturnCode  esr_status;

    init_status = 0;
    esr_status = PMemInit ( );

    if ( esr_status == ESR_SUCCESS )
        {
        PSTACK_SIZE_INIT ( );   /* I don't know what this is, it should probably have a status */
        }
    else
        {
        init_status = -1;
        /* Log Here */
        }
    return ( init_status );
    }



static int srec_test_shutdown_file_system ( void )
    {
    int shutdown_status;

    shutdown_status = 0;

    return ( shutdown_status );
    }



static int srec_test_init_file_system ( int arg_count, LCHAR *arg_vals [] )
    {
    int             init_status;

    init_status = 0;
    return ( init_status );
    }



static int srec_test_shutdown_logging_system ( PLogger *logger )
    {
    int shutdown_status;

    shutdown_status = 0;
    PLogShutdown ( );

    return ( shutdown_status );
    }



static int srec_test_init_logging_system ( int arg_count, LCHAR *arg_vals [], PLogger *logger )
    {
    int             init_status;
    ESR_ReturnCode  esr_status;

    init_status = 0;
    esr_status = PLogCreateFileLogger ( PSTDOUT, &logger );

    if ( esr_status == ESR_SUCCESS )
        {
        esr_status = PLogInit ( logger, 0 );

        if ( esr_status != ESR_SUCCESS )
            {
/*          pfclose ( (struct PFile_t *)logger );       I'm not sure this is correct, check with Gili */
            init_status = -1;
            /* Log Here */
            }
        }
    else
        {
        init_status = -1;
        /* Log Here */
        }
    return ( init_status );
    }



static int srec_test_init_audio_input ( AUDIOIN_H *audio_input_handle )
    {
    int                 init_status;
    LHS_AUDIOIN_ERROR   audio_status;

    init_status = 0;
    audio_status = lhs_audioinOpen ( WAVE_MAPPER, SREC_TEST_DEFAULT_AUDIO_FREQUENCY, audio_input_handle );

    if ( audio_status != LHS_AUDIOIN_OK )
        {
        init_status = -1;
        srec_test_log_error ( 0, ERROR_LEVEL_CRITICAL, "Audio Device Failed To Open" );
        }
    return ( init_status );
    }



static int srec_test_shutdown_audio_input ( AUDIOIN_H *audio_input_handle )
    {
    int                 shutdown_status;
    LHS_AUDIOIN_ERROR   audio_status;

    shutdown_status = 0;
    audio_status = lhs_audioinClose ( audio_input_handle );

    if ( audio_status != LHS_AUDIOIN_OK )
        {
        shutdown_status = -1;
        /* Log Here */
        }
    return ( shutdown_status );
    }



static int srec_test_shutdown_system ( PLogger *logger, AUDIOIN_H *audio_input_handle )
    {
    int shutdown_status;

    shutdown_status = srec_test_shutdown_audio_input ( audio_input_handle );

    if ( shutdown_status == 0 )
        {
        shutdown_status = srec_test_shutdown_logging_system ( logger );

        if ( shutdown_status == 0 )
            {
            shutdown_status = srec_test_shutdown_file_system ( );

            if ( shutdown_status == 0 )
                shutdown_status = srec_test_shutdown_memory_system ( );
            }
        }
    return ( shutdown_status );
    }




static int srec_test_init_system ( unsigned int srec_test_heap_size, PLogger* logger, int arg_count, LCHAR *arg_vals [], AUDIOIN_H *audio_input_handle )
    {
    int init_status;

   /* register signal handler so cleanup works on CTRL-C (Win32) */
#ifdef _WIN32
    signal(SIGINT, signal_handler_SIGINT);
#endif
    init_status = srec_test_init_memory_system ( srec_test_heap_size );

    if ( init_status == 0 )
        {
        init_status = srec_test_init_file_system ( arg_count, arg_vals );

        if ( init_status == 0 )
            {
            init_status = srec_test_init_logging_system ( arg_count, arg_vals, logger );

            if ( init_status == 0 )
                {
                init_status = srec_test_init_audio_input ( audio_input_handle );

                if ( init_status != 0 )
                    {
                    srec_test_shutdown_logging_system ( logger );
                    srec_test_shutdown_file_system ( );
                    srec_test_shutdown_memory_system ( );
                    }
                }
            else
                {
                srec_test_shutdown_file_system ( );
                srec_test_shutdown_memory_system ( );
                }
            }
        else
            {
            srec_test_shutdown_memory_system ( );
            }
        }
    return ( init_status );
    }



#if defined(_DEBUGHEAP) && defined(_DEBUG) && defined(WIN32)
_CrtMemState s0,s1,s2;



void OutputDivider( void )
    {

    _RPT1(_CRT_WARN, "%s", "********************************************************************\n");
    }



void OutputNewline( void )
    {

    _RPT1(_CRT_WARN, "%s", "\n");
    }
#endif



#if defined(_DEBUGHEAP) && defined(_DEBUG) && defined(WIN32)
void initialize_heap_logging ( void )
    {

     _CrtSetReportMode(_CRT_WARN,   _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_WARN,   _CRTDBG_FILE_STDOUT);
     _CrtSetReportMode(_CRT_ERROR,  _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_ERROR,  _CRTDBG_FILE_STDOUT);
     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
     _CrtMemCheckpoint(&s0);
     }
#endif



#if defined(_DEBUGHEAP) && defined(_DEBUG) && defined(WIN32)
void execute_heap_logging ( void )
    {
    OutputNewline();
    OutputDivider();
    _RPT1(_CRT_WARN, "%s", "After cleanup, before exiting main()\n");
    OutputDivider();
    _CrtMemCheckpoint(&s1);
    _CrtMemDifference(&s2, &s0, &s1);
    _CrtMemDumpStatistics(&s2);
    OutputNewline();
    OutputDivider();
    _RPT1(_CRT_WARN, "%s", "Checking for memory leaks...\n");
    OutputDivider();
    _CrtDumpMemoryLeaks();
    }
#endif



int main(int argc, LCHAR* argv [] )
    {
     int             test_status;
     unsigned int    num_shutdown_loops;
     unsigned int    current_shutdown_loop;
     unsigned int    num_continuous_run_loops;
     unsigned int    current_continuous_run_loop;
     unsigned int    srec_test_heap_size;

#ifdef _WIN32
    initStack();
#endif
        {
    /* This extra block is there to get a more precise estimate of the stack
      depth.  This way we also make sure that the local variables of main are
      taken into acount when estimating the stack size.
   */
        ApplicationData applicationData;
        PLogger         *logger;
        AUDIOIN_H       audio_in_handle;

        srec_test_heap_size = ( 4 * 1024 * 1024 );
        logger = NULL;
        test_status = srec_test_get_run_params ( &num_shutdown_loops, &num_continuous_run_loops );

        if ( test_status == 0 )
            {
            current_shutdown_loop = 0;

            while ( ( current_shutdown_loop < num_shutdown_loops )/* && ( test_status == 0 )*/ )
                {
#if defined(_DEBUGHEAP) && defined(_DEBUG) && defined(WIN32)
                initialize_heap_logging ( );
#endif
                test_status = srec_test_init_system ( srec_test_heap_size, logger, argc, argv, &audio_in_handle );

                if ( test_status == 0 )
                    {
                    current_continuous_run_loop = 0;

                    while ( ( current_continuous_run_loop < num_continuous_run_loops ) && ( test_status == 0 ) )
                        {
                        test_status = srec_test_init_application_data ( &applicationData, argc, argv );

                        if ( test_status == 0 )
                            {
                            test_status = srec_test_run_test ( &applicationData, audio_in_handle );
                            srec_test_shutdown_application_data ( &applicationData );
                            }
                        current_continuous_run_loop++;
                        }
                    test_status = srec_test_shutdown_system ( logger, &audio_in_handle );
                    }
                current_shutdown_loop++;
#if defined(_DEBUGHEAP) && defined(_DEBUG) && defined(WIN32)
                execute_heap_logging ( );
#endif
                }
            }
        }

    return ( test_status );
    }


